home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
pcmagazi
/
1992
/
04
/
screen.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-05
|
19KB
|
777 lines
// screen.cpp RHS 7/28/91
#include"screen.h"
#include<malloc.h>
#include<stdarg.h>
#include<stdio.h>
#include<string.h>
#include<process.h>
//#include"memwset.h"
OrgScreen Screen::orgScreen;
ScrDeskTop *Screen::DeskTop;
#ifdef OLD
int Screen::numlines;
int Screen::numcols;
char far *Screen::screenBuf;
unsigned far *Screen::curpos;
BYTE Screen::currAttr;
BYTE Screen::mode;
#else
SCRPARAMS Screen::params;
#endif
BOOL Screen::wait_for_retrace;
BOOL Screen::buffered;
unsigned Screen::bufsize;
char far *Screen::buffer;
char *Screen::workbuffer;
char *Screen::workbuf2;
void far *Screen::org_screen_image;
WORD Screen::org_screen_size;
WORD Screen::org_screen_curpos;
Screen *ScreenPtr = NULL;
Screen::Screen(void)
{
if(ScreenPtr)
return;
ScreenPtr = this;
orgScreen.params.screenBuf = NULL;
DeskTop = NULL;
BOOL printf_enabled = TRUE;
workbuffer = (printf_enabled) ? new char[DEFAULTLINELEN] : NULL;
workbuf2 = new char[DEFAULTLINELEN];
}
SCRPARAMS Screen::GetVidModeParams(BYTE *cols)
{
SCRPARAMS p;
p.mode = VidGetMode(cols); //(newmode != VIDMODE_DEFAULT ? VidGetMode(cols) : orgmode);
p.numcols = *cols;
if(p.mode == VIDMODE_C80)
if(*((char far *)0x00400084) > 24)
p.mode = VIDMODE_EGAVGA;
p.numlines = (p.mode != VIDMODE_EGAVGA) ? 25 : *((char far *)0x00400084) + 1;
p.screenBuf = (p.mode == VIDMODE_MONO) ? (char far *)0xB0000000 :
(char far *)0xB8000000;
p.currAttr = p.screenBuf[1];
BYTE row,col;
WORD start_stop;
_AH = 3;
_BH = 0;
asm int 10h;
row = _DH;
col = _DL;
start_stop = _CX;
p.curpos = (unsigned far *)&p.screenBuf[(row * *cols)+(col*2)];
p.currow = row;
p.curcol = col;
p.cursorSize = start_stop;
return p;
}
void Screen::Init(int newmode, BYTE desktop_colors, BYTE screen_colors)
{
BYTE cols;
if(!orgScreen.params.screenBuf)
{
orgScreen.params = GetVidModeParams(&cols);
// allocate space to save screen buffer and save it
org_screen_size = orgScreen.params.numlines*orgScreen.params.numcols;
if(org_screen_image = farmalloc(org_screen_size*2L))
CpyWords(org_screen_image,orgScreen.params.screenBuf,
org_screen_size);
}
if(newmode == VIDMODE_DEFAULT)
newmode = VidGetMode(NULL);
VidSetMode(newmode);
params = GetVidModeParams(&cols);
wait_for_retrace = (params.mode != VIDMODE_MONO) &&
(!CheckSysCopyRight((char far *)0xF000FFEAL,"COMPAQ")) &&
(!IsEgaVga());
params.currAttr = screen_colors;
buffered = FALSE;
buffer = NULL;
bufsize = 0;
// printf("newmode=%d\n",newmode);getchar();
if(DeskTop)
delete DeskTop;
DeskTop = new ScrDeskTop(desktop_colors, screen_colors);
}
void Screen::Paint(void)
{
if(DeskTop)
DeskTop->Paint();
else
Clear();
}
BOOL near pascal Screen::CheckSysCopyRight(char far *ROMaddress,
char *Copyright)
{
while (*Copyright)
if(*Copyright++ != *ROMaddress++)
return 0;
return 1;
}
BOOL near pascal IsEgaVga(void)
{
asm mov bl,10h /* make sure he has an EGA/VGA */
asm mov ah,12h
asm int 10h
asm cmp bl,10h
asm je NotEgaVga
EgaVga:
return TRUE;
NotEgaVga:
return FALSE;
}
void Screen::SetTextMode(int newmode)
{
Init(newmode);
}
Screen::~Screen(void)
{
if(this == ScreenPtr)
{
if(workbuffer)
{
delete workbuffer;
workbuffer = NULL;
}
if(workbuf2)
{
delete workbuf2;
workbuf2 = NULL;
}
if(DeskTop)
{
delete DeskTop;
DeskTop = NULL;
}
params = orgScreen.params;
}
if(this == ScreenPtr && orgScreen.params.screenBuf)
{
Init(params.mode);
// Paint();
if(org_screen_image)
{
CpyWords(params.screenBuf,org_screen_image,org_screen_size);
farfree(org_screen_image);
org_screen_image = NULL;
params.cursorSize = orgScreen.params.cursorSize;
Cursor(SCR_CURSOR_ON);
Cursor(orgScreen.params.currow,orgScreen.params.curcol);
}
}
}
void Screen::SetForeGround(unsigned char c)
{
(params.currAttr &= 0xf0) |= c; // clear foreground bits
}
void Screen::SetBackGround(unsigned char c)
{
(params.currAttr &= 0x0f) |= MakeBG(c); // clear background bits
}
void Screen::Clear(int row, int col, int erow, int ecol, BYTE colors)
{
#ifdef NOTYET
unsigned word = MakeCell(' ',params.currAttr);
// NOTE: Change this to use a snow-safe routine
memwset(params.screenBuf,word,params.numlines*params.numcols*2);
#else
int i,j;
j = (ecol-col);
if(j+col > params.numcols)
j = params.numcols-col;
Cursor(row,col);
WORD w = MakeCell(' ',colors);
for(i = row; i < erow && i < params.numlines; i++)
{
SetWords(params.curpos,w,j);
//Printf("%*s",j,"");
Cursor(i,col);
}
Cursor(row,col);
#endif
}
void cdecl Screen::Printf(char *fmt, ...)
{
if(!workbuffer)
return;
va_list argptr;
va_start(argptr,fmt);
vsprintf(workbuffer,fmt,argptr);
va_end(arg_ptr);
if(strchr(workbuffer,'\n'))
{
char *p = workbuffer, *q = &workbuffer[strlen(workbuffer)], *r = workbuffer;
unsigned count, width = params.numcols*2;
while((p < q) && (p = strchr(p,'\n')))
{
*p = '\0';
Write(r);
p++;
r = p;
count = (char far *)params.curpos-params.screenBuf;
params.curpos = (unsigned far *)(params.screenBuf + (((count / width)+1)*width));
}
}
else
Write(workbuffer);
}
void cdecl Screen::AtSay(int row,int col, char *fmt, ...)
{
if(!workbuffer)
return;
va_list argptr;
va_start(argptr,fmt);
vsprintf(workbuffer,fmt,argptr);
va_end(arg_ptr);
Cursor(row,col);
Write(workbuffer);
}
void Screen::Buffering(BOOL on)
{
if(on)
{
if(buffered)
return;
buffered = TRUE;
buffer = (char far *)farmalloc(bufsize = (params.numlines*params.numcols*2));
VidRamAccess(buffer,params.screenBuf,params.numlines*params.numcols*2);
}
else
{
if(!buffered)
return;
buffered = FALSE;
VidRamAccess(params.screenBuf,buffer,bufsize); // flush buffer
bufsize = 0;
farfree(buffer);
buffer = NULL;
}
}
WORD far *Screen::Cursor(int x, int y)
{
_BH = 0;
_DH = x;
_DL = y;
_AH = 2;
asm int 10h
return params.curpos = (unsigned far *)
(¶ms.screenBuf[(x*params.numcols*2)+(y*2)]);
}
void Screen::Cursor(BOOL on)
{
if(on)
{
_CX = params.cursorSize;
_AH = 1;
asm int 10h;
}
else
{
_BH = 0;
_AH = 3;
asm int 10h;
params.cursorSize = _CX;
_CX = 0x2000;
_AH = 1;
asm int 10h;
}
}
void Screen::Write(char *str,WORD clr)
{
Write((unsigned char *)str, clr, strlen(str));
}
void Screen::Write(unsigned char *str, WORD clr, int len)
{
int i;
unsigned *u = (unsigned *)workbuf2, attrmask;
attrmask = MakeCell(0,clr);
//((params.currAttr << 8) & 0xff00);
for(i = 0; i < len; i++, u++)
*u = (attrmask | str[i]);
if(!buffered)
{
VidRamAccess(params.curpos,workbuf2,len);
params.curpos += (len);
}
}
void Screen::WriteRaw(void far *buf, int len)
{
VidRamAccess(params.screenBuf,buf,len);
}
void Screen::Read(char *str)
{
Read(str, strlen(str));
}
void Screen::Read(char *str, int len)
{
VidRamAccess(str,params.curpos,len);
}
void Screen::ReadRaw(void far *buf, int len)
{
VidRamAccess(buf,params.screenBuf,len);
}
void Screen::FlushBuffer(void)
{
if(!buffered)
return;
VidRamAccess(params.screenBuf,buffer,bufsize);
}
// VidRamAccess - moves len bytes of video RAM from scr to dst and checks
// for snow
void near pascal Screen::VidRamAccess(void far *dst, void far *src, int len)
{
#if defined(JUNK)
int Snow;
Snow = wait_for_retrace;
asm push ds
asm mov cx, len // Length value into CX
asm jcxz Exit
asm les di, dst // Get pointers to data area
asm lds si, src
asm cld // Setup move direction
asm cmp si, di // Check for move direction
asm jae SnowTest // Moving down?, then forward move ok
asm mov ax, cx // Nope, then start at other end
asm dec ax
asm shl ax, 1
asm add si, ax
asm add di, ax
asm std
SnowTest:
asm cmp word ptr Snow, 0 // Does video card snow ?
asm jnz StopSnow // Yes, wait for retrace
asm rep movsw // Suppose to do both, do normal move
asm jmp short Exit // All done
StopSnow:
asm mov dx, 3DAh // Suppose to wait, Point DX to CGA status port
asm mov ax, es // See if both are in video seg
asm mov bx, ds
asm cmp ax, bx
asm je VIOStopSnow // Have to wait to and fro
Wait4HRetrace:
asm cli // No ints during critical section
Synchronize:
asm in al, dx // Get 6845 status
asm ror al, 1 // In horizontal retrace ?
asm jc Synchronize // If on, wait for cycle to end
WaitForNext:
asm in al, dx // Get 6845 status
asm ror al, 1 // In horizontal retrace ?
asm jnc WaitForNext // No, wait for it to begin
asm movsw // Move video ram word
asm sti // Allow interrupts
asm loop Wait4HRetrace // Next byte
asm jmp short Exit
VIOStopSnow:
VInWait4HRetrace:
asm cli // No ints during critical section
VInSynchronize:
asm in al, dx // Get 6845 status
asm ror al, 1 // In horizontal retrace ?
asm jc VInSynchronize // If on, wait for cycle to end
VInWaitForNext:
asm in al, dx // Get 6845 status
asm ror al, 1 // In horizontal retrace ?
asm jnc VInWaitForNext // No, wait for it to begin
asm lodsw // Get word from video ram
asm sti // Allow interrupts
asm mov bx, ax // Save word
asm cli // No ints during critical section
VOutSynchronize:
asm in al, dx // Get 6845 status
asm ror al, 1 // In horizontal retrace ?
asm jc VOutSynchronize // If on, wait for cycle to end
VOutWaitForNext:
asm in al, dx // Get 6845 status
asm ror al, 1 // In horizontal retrace ?
asm jnc VOutWaitForNext // No, wait for it to begin
asm mov ax, bx // Get word to store
asm stosw // Put word in video ram
asm sti // Allow interrupts
asm loop VInWait4HRetrace // Next byte
Exit:
asm cld // Restore Direction Flag
asm pop ds
#endif
#if defined(JUNK)
int i;
if(len % 2)
{
BYTE far *dest = (BYTE far *)dst;
BYTE far *sorc = (BYTE far *)src;
for(i = 0; i < len; i++)
dest[i] = sorc[i];
}
else
{
WORD far *dest = (WORD far *)dst;
WORD far *sorc = (WORD far *)src;
for(i = 0; i < len; i++)
dest[i] = sorc[i];
}
#else
CpyWords(dst,src,len);
#endif
return;
}
// propogates 'val' starting at 'addr', for 'len' repetitions
void near pascal SetWords(void far *addr, unsigned val, unsigned len)
{
asm les di, addr
asm mov cx, len
asm mov ax, val
asm cld
asm rep stosw
}
void near pascal CpyWords(void far *dst, void far *src, unsigned n)
{
asm mov dx,ds
asm les di, dst
asm lds si, src
asm mov cx,n
// asm shr cx,1
asm cld
asm rep movsw
// asm jnc cpy_end
// asm movsb
cpy_end:
asm mov ds,dx
}
void near pascal VidSetMode(BYTE mode)
{
/********** Turbo does this for us ************
asm push si
asm push di
***********************************************/
asm push ds
_AH = VIDSETMODE;
_AL = mode;
asm push cx
asm mov cx,40h /* ds = BIOS video data area */
asm mov ds,cx
asm pop cx
asm cmp al,VIDMODE_C80
asm jne NotC80
asm mov ax,1a00h /* is this an EGA? */
asm int 10h
asm cmp al,1ah
asm je NotEGA
asm and byte ptr ds:[87h],0feh /* update BIOS data area */
NotEGA:
asm mov ah,1 /* set cursor size */
asm mov cx,0607h
asm int 10h
asm mov ax,VIDMODE_C80
NormalCall:
asm int 10h
asm jmp Exit
NotC80:
asm cmp al,VIDMODE_EGAVGA
asm jne NormalCall
IsEgaVga(); // see if he has EGA
asm cmp ax,0
asm je Exit
asm mov ax,1112h /* load 8x8 character set */
asm xor bl,bl
asm int 10h
asm mov ax,1200h /* select alternate print-screen routine */
asm mov bl,20h
asm int 10h
asm mov ax,1a00h /* is this a VGA? */
asm int 10h
asm cmp al,1ah
asm je Exit
asm or byte ptr ds:[87h],1 /* update BIOS data area */
asm mov ah,1 /* set cursor size */
asm mov cx,0600h
asm int 10h
asm jmp Exit
Exit:
asm pop ds
/********** Turbo does this for us ************
asm pop di
asm pop si
***********************************************/
}
BYTE near pascal VidGetMode(BYTE *cols)
{
/********** Turbo does this for us ************
asm push si
asm push di
***********************************************/
asm push ds
_AH = VIDGETMODE;
asm push cx
asm mov cx,40h /* ds = BIOS video data area */
asm mov ds,cx
asm pop cx
//GetMode:
asm int 10h
asm cmp al,VIDMODE_C80
asm jne Exit
asm push ax
IsEgaVga();
asm or al,al
asm pop ax
asm jz Exit
asm cmp byte ptr ds:[84h],24
asm je Exit
asm mov al,VIDMODE_EGAVGA
Exit:
asm pop ds
if(cols)
*cols = _AH;
/********** Turbo does this for us ************
asm pop di
asm pop si
***********************************************/
return _AL;
}
ScrDeskTop::ScrDeskTop(BYTE clr, BYTE attr, BYTE fchar)
{
fillchar = fchar;
color = clr;
attributes = attr;
}
BOOL pascal ScrDeskTop::Paint(void)
{
#if defined(SNOWCHECK)
BYTE far *temp;
int i,j, clientheight, clientwidth;
clientheight = ScreenPtr->Lines();
clientwidth = ScreenPtr->Columns();
if(!(temp = (BYTE far *)farmalloc(clientheight*clientwidth*2L)))
return FALSE;
j = clientheight * clientwidth * 2;
for( i = 0; i < j; )
{
temp[i++] = fillchar;
temp[i++] = color;
}
ScreenPtr->WriteRaw(temp,j);
for( i = 0, j = clientwidth*2; i < j; )
{
temp[i++] = ' ';
temp[i++] = color;
}
if(attributes & SCR_MENU_BAR)
{
clientheight--;
ScreenPtr->WriteRaw(temp,j);
}
if(attributes & SCR_STATUS_BAR)
{
clientheight--;
ScreenPtr->VidRamAccess(
&ScreenPtr->params.screenBuf[(clientheight+1)*clientwidth*2],
temp,
j);
}
farfree(temp);
return FALSE;
#else
#define NEW
BYTE far *temp;
int i,j, clientheight, clientwidth;
clientheight = ScreenPtr->Lines();
clientwidth = ScreenPtr->Columns();
temp = (BYTE far *)ScreenPtr->params.screenBuf;
j = clientheight * clientwidth * 2;
#ifdef NEW
WORD w = MakeCell(fillchar,color);
SetWords(temp,w,j/2);
#else
for( i = 0; i < j; )
{
temp[i++] = fillchar;
temp[i++] = color;
}
#endif
j = clientwidth*2;
if(attributes & SCR_MENU_BAR)
{
#ifdef NEW
w = MakeCell(' ',color);
SetWords(temp,w,j/2);
#else
for( i = 0; i < j; )
{
temp[i++] = ' ';
temp[i++] = color;
}
#endif
clientheight--;
}
if(attributes & SCR_STATUS_BAR)
{
clientheight--;
BYTE far *temp2 = (BYTE far *)
&ScreenPtr->params.screenBuf[(clientheight+1)*clientwidth*2];
#ifdef NEW
w = MakeCell(' ',color);
SetWords(temp2,w,j/2);
#else
for(i = 0; i < j; i++)
temp2[i] = temp[i];
#endif
}
return FALSE;
#endif
}
void Screen::Exec(char *command, char *args[], char *message)
{
void far *screenbuf = farmalloc(params.numlines*params.numcols*2*1L);
if(!screenbuf)
return;
// save current screen
CpyWords(screenbuf,params.screenBuf,params.numlines*params.numcols*1L);
// ************************************* ADD facilities to handle change of mode
// restore original screen image
// CpyWords(params.screenBuf,org_screen_image,params.numlines*params.numcols*1L);
Cursor(SCR_CURSOR_ON); // turn cursor on
BOOL isDos = FALSE;
char *p = strstr(strupr(command),"COMMAND.COM");
if(p && (p == command || p[-1] == '\\' || p[-1] == ':'))
{
isDos = TRUE;
VidSetMode(orgScreen.params.mode);
_DH = orgScreen.params.numlines-1;
_DL = orgScreen.params.numcols-1;
_CX = 0;
_BH = orgScreen.params.currAttr;
_AH = 6;
_AL = orgScreen.params.numlines;
asm int 10h;
}
if(message)
printf(message);
// extern int errno;
// errno = 0;
spawnvp(P_WAIT,command,args);
// printf("errno=%d\n",errno);
if(isDos)
VidSetMode(params.mode);
Cursor(SCR_CURSOR_OFF);
// ************************************* ADD facilities to handle change of mode
// CpyWords(org_screen_image,params.screenBuf,params.numlines*params.numcols*1L);
// restore current screen
CpyWords(params.screenBuf,screenbuf,params.numlines*params.numcols*1L);
farfree(screenbuf);
}